
; B5MH-3.INS - BYE5 insert for Morrow MD5, MD11, MD16, MD34 - 10/10/85
;
;				Z80 SIO
;
;		    This is an insert, not an overlay
;
; This insert adapts the Morrow computers using hard disk and CP/M+
; with banked memory to BYE5.
;
;
;=   =	 =   =	 =   =	 =   =	 =   =	 =   =	 =   =	 =   =	 =   =
;
; 10/10/85  Reorganized and simplified. - Ed Meyer
;  B5MH-3
;
; 08/25/85  Fixed BUG in the Morrow BIOS INTER-BANK routine.
;  B5MH-2				- Paul Bartholomew
;
; 08/17/85  Updated for compatibility with BYE501.
;  B5MH-1				- George Peace
;
;=   =	 =   =	 =   =	 =   =	 =   =	 =   =	 =   =	 =   =	 =   =
;
;
; To get this to work correctly with a Morrow MD-HD, you must use the
; following cable configuration:
;
;	      Modem End 	  Morrow MD-HD End
;	      ========= 	  ================
;		GND  1 <--------> 1  GND - ground
;		 TD  2	--------> 3  RD  - receive data
;		 RD  3 <--------  2  TD  - transmit data
;		 SG  7 <--------> 7  SG  - signal ground
;		 CD  8	--------> 4  CD  - carrier detect
;		DTR 20 <--------  5  DTR - data terminal ready
;
;
; Depending on the setting of the jumpers inside your computer, pins 2
; and 3 may or may not need to be crossed.
;
; MAKE SURE THE JUMPERS INSIDE THE MORROW ARE SET TO FACTORY SETTINGS.
;  (See Appendix D, figures D-5 and D-6 of the MD-11 users guide)
;
; NOTE: The CD (Carrier Detect) line is connected the Morrow pin 4 (RTS
;	on most computers, while usually pin 8 is carrier detect.)
;
;-----------------------------------------------------------------------
;
;
; Set ONE of the following to YES, the other to NO
;
PMPORT	EQU	NO		; Yes, using "Printer/Modem" port
AUXPORT	EQU	YES		; Yes, using "Auxilliary" port
;
PORT	EQU	060H		; Port for local console output
CONST	EQU	PORT+1		; Local console status
;
;
	 IF	PMPORT
BPORT	EQU	062H
BAUDS	EQU	051H
MODEW	EQU	07EH
	 ENDIF			; PMPORT

	 IF	AUXPORT
BPORT	EQU	070H
BAUDS	EQU	050H
MODEW	EQU	03EH
	 ENDIF			; AUXPORT
;
;
; The following define the port addresses to use.
;
DPORT	EQU	BPORT		; Data port
MDCTL1	EQU	BPORT+1		; Status/control port
BRPORT	EQU	053H
;
;
; The following are MDCTL1 status masks
;
MDRCV	EQU	1		; Data available
MDSND	EQU	4		; Transmit buffer empty
DCD	EQU	8		; Data carrier detect
;
;-----------------------------------------------------------------------
;
;
; See if we still have a carrier - if not, return with the zero flag set
;
MDCARCK:MVI	A,10H		; Reset status
	OUT	MDCTL1
	IN	MDCTL1		; Get status
	ANI	DCD		; Check for data carrier
	RET			; Return
;.....
;
;
; Disconnect and wait for an incoming call
;
MDINIT:	MVI	A,18H		; Reset channel
	OUT	MDCTL1
	MVI	A,4		; Setup to write register 4
	OUT	MDCTL1
	MVI	A,44H		; No parity, 1 stop, 16x
	OUT	MDCTL1
	MVI	A,1		; Setup to write register 1
	OUT	MDCTL1
	MVI	A,0
	OUT	MDCTL1
	MVI	A,5		; Setup to write register 5
	OUT	MDCTL1
	MVI	A,0		; DTR, RTS both off
	OUT	MDCTL1
	PUSH	B		; Save in case it's being used elsewhere
	MVI	B,20		; 2 second delay
;
OFFTI:	CALL	DELAY		; 0.1 second delay
	DCR	B
	JNZ	OFFTI		; Keep looping until finished
	POP	B		; Restore bc
	MVI	A,3		; Setup to write register 3
	OUT	MDCTL1
	MVI	A,0C1H		; 8 bits, enable receive
	OUT	MDCTL1
	MVI	A,5		; Setup to write register 5
	OUT	MDCTL1
	MVI	A,0EAH		; DTR, RTS, TX on, 8 bits
	OUT	MDCTL1

	 IF	IMODEM		; If using intelligent modem
	CALL	IMINIT		; Go initialize modem now
	 ENDIF			; IMODEM
;
	RET			; Return
;.....
;
;
; Input a character from the modem port
;
MDINP:
	IN	DPORT		; Get character
	RET			; Return
;.....
;
;
; Check the status to see if a character is available.	If not, return
; with the zero flag set.  If yes, use 0FFH to clear the flag.
;
MDINST:
	IN	MDCTL1		; Get status
	ANI	MDRCV		; Got a character?
	RZ			; Return if none
	ORI	0FFH		; Otherwise, set the proper flag
	RET			; And return
;.....
;
;
; Send a character to the modem
;
MDOUTP:	OUT	DPORT		; Send it
	RET			; Return
;.....
;
;
; See if the output is ready for another character
;
MDOUTST:
	IN	MDCTL1
	ANI	MDSND		; Mask it
	RET			; Return
;.....
;
;
; Reinitialize the modem and hang up the phone by dropping DTR and
; leaving it inactive.
;
MDQUIT:	 IF	IMODEM		; If using an intelligent modem
	CALL	IMQUIT		; Tell it to shut down
	 ENDIF			; IMODEM
;
;
; Called by the main program after caller types BYE.
;
MDSTOP:	MVI	A,5		; Setup to write register 5
	OUT	MDCTL1
	MVI	A,0		; Clear DTR, RTS causing shutdown
	OUT	MDCTL1
	RET
;.....
;
;
; The following routine sets the baudrate.  BYE5 asks for the maximum
; speed you have available.
;
SETINV:	MVI	A,0FFH
	ORA	A		; Make sure the zero flag is set
	RET
;.....
;
;
SET300:	LXI	H,BD300
	JMP	SETBAUD
;.....
;
;
SET1200:LXI	H,BD1200
	JMP	SETBAUD
;.....
;
;
SET2400:LXI	H,BD2400
	JMP	SETBAUD
;.....
;
;
SETBAUD:MVI	A,MODEW
	OUT	BRPORT
	MOV	A,M
	OUT	BAUDS
	INX	H
	MOV	A,M
	OUT	BAUDS
	XRA	A		; Say rate is ok
	RET			; Return
;.....
;
;
; The following are baud rates for BPORT -- they will have to be changed
; for your particular CTC.
;
BD300: DW	832
BD1200:DW	208
BD2400:DW	104
BD9600:DW	26


;.....
;
;
;Find address of INTER-BANK BUG in Morrow's BIOS
;
FINDBUG:LDA	FNDBUG		; See if we already found the address
	ORA	A
	JZ	FBUG0		; No, go find it
	LHLD	BUGADR		; Yes, return with address
	RET
;.....
;
;
FBUG0:	LHLD	1
	INX	H
	MOV	E,M
	INX	H
	MOV	D,M
	XCHG			; Hl points to warm boot code
;
;
; The warm boot in common memory is as follows:
;
; loc  opcodes	mneumonics
; ---- -------	--------------------
; xxxx 21 yyyy	LD	HL,BNK-WBOOT ;WARM BOOT code in SYSTEM bank
; xxxx 18 zz	JR	INTER-BANK
;
; We will find the address of INTER-BANK and modify it to fix the BUG.
;
; The INTER-BANK code in COMMON memory is as follows:
;
; loc  opcodes	mneumonics
; ---- -------	--------------------
; xxxx 3A yyyy	LD	A,(SYSMTE-BANK-BITS)
; xxxx CB 47	BIT	0,A	;Should be BIT 1,A (CB 4F)
;
;
;
FBUG1:	MOV	A,M
	CPI	18H		; Look for JR to INTER-BANK
	JZ	FBUG2
	INX	H
	JMP	FBUG1
;
FBUG2:	INX	H
	MOV	A,M		; Get JR offset
	INX	H
	MOV	E,A
	MVI	D,0
	DAD	D		; HL now points to INTER-BANK
;
FBUG3:	MOV	A,M
	CPI	0CBH		; Look for bit opcode
	JZ	FBUG4
	INX	H
	JMP	FBUG3
;
FBUG4:	INX	H
	SHLD	BUGADR
	MVI	A,0FFH
	STA	FNDBUG
	RET
;.....
;
;
FNDBUG:	DB	0
BUGADR:	DW	0
BUGVAL:	DB	0
;.....
;
;
; Perform system or hardware dependent PRE-processing.	The following
; code will be executed by the PATCH subroutine before the BIOS jump
; table is overwritten.  This will allow the BIOS intercept routines to
; operate as early as the initial signon message display.
;
MDPREP:	CALL	FINDBUG		; Get address of BIOS bug
	MOV	A,M
	STA	BUGVAL		; Save old value
	MVI	M,04FH		; Change the bit 0,A to a bit 1,A
;
;
; OK, the BIOS BUG is now fixed.
;
;
; Replace the NEWJTBL BIOS routing table with our own
;
;
	LXI	H,JTBLNEW	; Get replacement table address
	LXI	D,NEWJTBL	; Get address to overwrite
	LXI	B,JTBLEN	; Get number of bytes to overwrite
	DB	0EDH,0B0H	; Move the jump table
;
;
; Move the BIOS intercept routines up to common memory
;
	LXI	H,STCOMN	; Start of interface routines
	LXI	D,COMMN		; Address in high memory to load them
	LXI	B,COMLEN	; Length of common code
	DB	0EDH,0B0H	; Move the code to common memory
	RET
;.....
;
;
; Perform system or hardware dependent POST-processing.  The following
; code will be executed by the EXCPM routine before returning control to
; CP/M Plus when the BYE5 program is terminated.
;
MDPOSP:	CALL	FINDBUG		; Get address of BIOS bug
	LDA	BUGVAL		; Get old value
	MOV	M,A		; Un-fix the BIOS bug (make it a bit 0)
	RET
;.....
;
;
; The following code is required for proper operation on the Morrow
; MD-HD.  As the MD-HD operates in a banked environment, BIOS calls MAT
; originate in any bank (0 or 1).  It is therefore possible that window
; 1 (where BYE5 resides) will not be selected at the time a BIOS call is
; made.  As a result, steps must be taken to be sure that the BIOS jump
; table does not direct a BIOS call into bank 1 unless that bank is
; selected.  This code is moved up to common memory where it will be
; visible to all banks.  For each of the intercepted BIOS calls, it will:
;
;   - save the caller's stack pointer
;   - save the caller's bank select mask
;   - switch to bank 1
;   - execute the BYE interface routine and then the
;	original BIOS routine as necessary
;   - recover the caller's stack pointer
;   - reset the bank select mask to that of the caller
;   - return control to the caller
;
;
;NOTE: With Morrow MD-HD computers (BIOS <= 2.0), the free common memory
;      is from FF48H to FFA9H (97 bytes).  Make sure COMLEN is <= 61H!
;
;      All other common RAM is used by BIOS for stacks and interrupts.
;
;
COMMN	EQU	0FF48H		; Address for unmodified bios <= 2.0
;
SXBIOS	EQU	0F885H		; Address of stack for BIOS intercepts
;
PNTSELM	EQU	0FE51H+1	; Pointer to SELMEN JMP +1
;
BNKSTB	EQU	41H		; Bank select port
;
STCOMN	EQU	$
;
WBCOMN	EQU	COMMN+($-STCOMN) ; Warm boot
	CALL	SWIN
	JMP	MBOOT
;.....
;
;
CSCOMN	EQU	COMMN+($-STCOMN) ; Console status
	CALL	SWIN
	CALL	MSTAT
	JMP	SWOUT
;....
;
;
CICOMN	EQU	COMMN+($-STCOMN) ; Console input
	CALL	SWIN
	CALL	MINPUT
	JMP	SWOUT
;.....
;
;
COCOMN	EQU	COMMN+($-STCOMN) ; Console output
	CALL	SWIN
	CALL	MOUTPUT
	JMP	SWOUT
;.....
;
;
SWIN	EQU	COMMN+($-STCOMN) ; Bank switch in routine
				; Destroys register HL,A
	POP	H		; Get return address
	DB	0EDH,073H
	DW	SXSAVE
	LXI	SP,SXBIOS	; Load new stack pointer in common
	PUSH	H
	CALL	FNDSBB		; HL=address of SYSTEM-BANK-BITS
	MOV	A,M
	RRC			; Bank # in bit 1, move to bit 0
	ANI	1		; A now has the current bank in it
	POP	H
	PUSH	PSW		; Save it for return from BIOS
	MVI	A,1		; Get bank 1 mask
	CALL	SELMEM
	PUSH	H		; Put return address on new stack
	RET
;.....
;
;
SWOUT	EQU	COMMN+($-STCOMN) ; Bank switch out routine
	MOV	H,A		; Save A reg. (for console input call)
	POP	PSW		; Retrieve caller's bank selection mask
	DB	0EDH,07BH
	DW	SXSAVE
	CALL	SELMEM
	MOV	A,H		; Restore A reg. (for console input call)
	RET
;.....
;
;
SELMEM	EQU	COMMN+($-STCOMN)
	PUSH	H
	LHLD	PNTSELM
	CALL	MYPC
	POP	H
	RET
;.....
;
;
MYPC	EQU	COMMN+($-STCOMN)
	PCHL
;.....
;
;
FNDSBB	EQU	COMMN+($-STCOMN) ; Point HL to SYSMTE-BANK-BITS
	PUSH	D
	LHLD	PNTSELM
	INX	H
	INX	H
	MOV	E,M
	INX	H
	MOV	D,M		; DE points to SYSTEM-BANK-BITS
	XCHG
	POP	D
	RET
;.....
;
;
SXSAVE	EQU	COMMN+($-STCOMN)
	DS	2		; Save area for caller's stack pointer
;
COMLEN	EQU	$-STCOMN	; Length of common memory interface code
;
JTBLNEW:
	JMP	MCBOOT		; Cold boot
	JMP	WBCOMN		; Warm boot
	JMP	CSCOMN		; Modem status test
	JMP	CICOMN		; Modem input routine
	JMP	COCOMN		; Modem output routine
;
	 IF	(NOT HARDLOG) AND (NOT PRINTER)
	JMP	COCOMN		; Modem list device
	JMP	COCOMN		; Modem punch device
	JMP	CICOMN		; Modem reader device
	 ENDIF			; (NOT HARDLOG) AND (NOT PRINTER)
;
JTBLEN	EQU	$-JTBLNEW
;
;			       end
;----------------------------------------------------------------------
